import cv2
import copy
import numpy as np


img = cv2.imread("Rice.jpg", flags=1)
grey = cv2.imread("Rice.jpg", flags=0)
cv2.imshow("original image", img)
cv2.imshow("grey", grey)

dst = cv2.adaptiveThreshold(grey, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 101, 1)  # 局部大津算法
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))  # 形态学运算的结构元素
bw = cv2.morphologyEx(dst, cv2.MORPH_OPEN, element)

seg = copy.deepcopy(bw)
bin, cnts, hier = cv2.findContours(seg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 检测米粒轮廓

# 分析目标
count = 0
area_array = np.array([])  # 米粒面积数组
line_array = np.array([])  # 米粒长度数组
for i in range(len(cnts), 0, -1):
    cnt = cnts[i - 1]
    area = cv2.contourArea(cnt)  # 米粒面积
    if area < 10:
        continue
    count = count + 1
    area_array = np.append(area_array, area)

    minAreaRect = cv2.minAreaRect(cnt) # 精确米粒边界
    x, y, z, p = cv2.boxPoints(minAreaRect)  # 得到米粒的4个坐标
    # 计算米粒的长度
    l1 = ((x[0] - y[0]) ** 2 + (x[1] - y[1]) ** 2) ** 0.5 # 计算米粒边界长度
    l2 = ((x[0] - p[0]) ** 2 + (x[1] - p[1]) ** 2) ** 0.5
    if l1 > l2:
        line = l1
    else:
        line = l2
    print("米粒", i, "面积:", area, "长度:", round(line, 2))
    line_array = np.append(line_array, line)
    cv2.line(img, tuple(x), tuple(y), (255, 0, 0), 1)
    cv2.line(img, tuple(y), tuple(z), (255, 0, 0), 1)
    cv2.line(img, tuple(z), tuple(p), (255, 0, 0), 1)
    cv2.line(img, tuple(p), tuple(x), (255, 0, 0), 1)
    cv2.putText(img, str(count), (x[0], x[1]), cv2.FONT_HERSHEY_PLAIN, 0.5, (0, 0xff, 0)) # 标记字体信息

print("------------------------------")

print("米粒总数量: ", len(area_array))
print("------------------------------")

area_all = area_array.sum()
print("总面积:", round(area_all, 3))
average_area = area_all / count
print("平均面积:", round(average_area, 3))
std = area_array.std()
print("面积标准差:", round(std, 3))
area1 = average_area - std * 1.5
area2 = average_area + std * 1.5
print("面积3sigma的取值范围:", round(area1, 3), "--", round(area2, 3))
count1 = 0
for i in area_array:
    if i > area1 and i < area2:
        count1 = count1 + 1
print("米粒面积在3sigma内的数量为:", count1)

print("------------------------------")

line_all = line_array.sum()
print("总长度:", round(line_all, 3))
average_line = line_all / count
print("平均长度:", round(average_line, 3))
std_line = line_array.std()
print("长度标准差:", round(std_line, 3))
line1 = average_line - std_line * 1.5
line2 = average_line + std_line * 1.5
print("长度3sigma的取值范围:", round(line1, 3), "--", round(line2, 3))
count2 = 0
for i in line_array:
    if line2 > i > line1:
        count2 = count2 + 1
print("米粒长度在3sigma内的数量为:", count2)

print("------------------------------")

cv2.imshow("fenGeTu", img)  # 显示标记后的图
cv2.waitKey()
cv2.imshow("yuZhiHuaTu: ", bw)
cv2.waitKey()

cv2.destroyAllWindows()
